#!/usr/bin/env python
#_*_ coding:UTF-8 _*_
# 多进程程锁服务器

import socket, traceback, os, sys, fcntl, time

def getlastaccess(fd, ip):
    fcntl.flock(fd, fcntl.LOCK_SH)

    try:
        fd.seek(0)

        for line in fd.readlines():
            fileip, accesstime = line.strip().split("|")
            if fileip == ip:
                return accesstime

        return None
    finally:
        fcntl.flock(fd, fcntl.LOCK_UN)


def writelastaccess(fd, ip):
    fcntl.flock(fd, fcntl.LOCK_EX)
    records = []

    try:
        fd.seek(0)
        for line in fd.readlines():
            fileip, accesstime = line.strip().split("|")
            if fileip != ip:
                records.append((fileip, accesstime))

        fd.seek(0)

        for fileip, accesstime in records + [(ip, time.asctime())]:
            fd.write("%s|%s\n" % (fileip, accesstime))
        fd.truncate()

    finally:
        fcntl.flock(fd, fcntl.LOCK_UN)


def reap():
    while True:
        try:
            result = os.waitpid(01, os.WNOHANG)
            if not result[0]:break

        except:
            break

        print "Reaped child process %d" % result[0]


host = ''
port = 51423


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)


fd = open("lastaccess.txt", "w+")

while True:
    try:
        clientsock, cliengaddr = s.accept()

    except(KeyboardInterrupt):
        raise
    except:
        traceback.print_exc()
        continue

    reap()

    pid = os.fork()
    if pid:
        clientsock.close()
        continue
    else:
        s.close()


    try:
        print "Got connection from %s, servicing with PID %d" %(clientsock.getpeername(), os.getpid())
        ip = clientsock.getpeername()[0]
        clientsock.sendall("Welcome, %s.\n" % ip)
        last = getlastaccess(fd, ip)
        if last:
            clientsock.sendall("I last saw you seen you before.\n")
        else:
            clientsock.sendall("I've never seen you before.\n")

        writelastaccess(fd, ip)
        clientsock.sendall("I hava noted your connecton at %s.\n" % getlastaccess(fd, ip))

    except(KeyboardInterrupt, SystemExit):
        raise
    except:
        traceback.print_exc()

    try:
        clientsock.close()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()

    sys.exit(0)




